/**
 * @file       Frame.cpp
 * @brief      TODO
 * @author     Huabo Zheng
 * @date       Jan 12, 2012
 * @Copyright  2012, www.netgear.com Inc. All rights reserved.
 */

#include "lcd/IDisplay.h"
#include "Frame.h"
#include "Rect.h"
#include "errorcode.h"
#include "Context.h"
#include "Panel.h"
#include "lcd/LCDFactory.h"
#include "EventQueue.h"
#include "AppEvent.h"
#include "KeyboardListener.h"

namespace NS_LCD_AFW
{

CFrame::CFrame() :
		m_bFocusable(false), m_bHasFocus(false), m_bHightlightable(false), m_bIsHightlight(
				false), m_bIsVisible(true),m_bCursorable(false),m_bHasCursor(false), m_pParent(NULL), m_frameRect(0, 0,
				0, 0), m_position(0, 0), m_strFrameName("")
{
}

CFrame::~CFrame()
{
	m_pParent = NULL;
	this->setFocus(false);
	this->setHightlight(false);
}

CRect &CFrame::getRect()
{
	return m_frameRect;
}

CFrame *CFrame::getParent() const
{
	return m_pParent;
}

std::string CFrame::getName() const
{
	return m_strFrameName;
}

bool CFrame::isFocusable() const
{
	return m_bFocusable;
}

bool CFrame::hasFocus() const
{
	return m_bHasFocus;
}

int CFrame::create(const std::string & name, const CRect & rect,
		CFrame *pParent, CContext *pContext)
{
	int iRet = ERR_SUCCESS;
	this->setName(name);
	this->setRect(rect);
	this->setParent(pParent);
	this->preCreate();
	if (NULL == pParent)
	{
		//this->setPosition(rect.getLeftTop());
	}
	if (name.empty())
	{
		iRet = ERR_FRAME_NAME_EMPTY;
	}
	else if (!rect.isValidRect())
	{
		iRet = ERR_INVALID_RECT;
	}
	if (iRet == ERR_SUCCESS)
	{
		return this->onCreate();
		//not a good designed ~!~
//		if (typeid(*pParent) == typeid(CPanel))
//		{
//			((CPanel *)pParent)->add(this);
//		}
	}
	return iRet;
}

void CFrame::setHightlightable(bool bHightlightable)
{
	this->m_bHightlightable = bHightlightable;
}

bool CFrame::isHightlightable() const
{
	return m_bHightlightable;
}

void CFrame::setCursorable(bool bCursorable)
{
	 this->m_bCursorable = bCursorable;
}

bool CFrame::isCursorable() const
{
	return this->m_bCursorable;
}

bool CFrame::isHightlight() const
{
	return m_bIsHightlight;
}

int CFrame::setHightlight(bool bHightlight)
{
	if (this->isHightlightable())
	{
		if (bHightlight == this->isHightlight())
		{
			return ERR_NO_CHANGE;
		}

		this->m_bIsHightlight = bHightlight;

		m_bIsHightlight ? this->onHightlight() : this->onUnHightlight();
		return this->invalidate();
	}
	return ERR_UN_HIGHTLIGHT_ABLE;
}

void CFrame::setFocusable(bool bFocusable)
{
	m_bFocusable = bFocusable;
}

int CFrame::notify(IEvent *pEvent)
{
	int iRet = ERR_SUCCESS;
	if (ERR_SUCCESS != (iRet = CEventHandler::notify(pEvent)))
	{
		if (NULL != this->getParent() &&  this->getParent()->isVisible())
		{
			//this->getParent()->setFocus(true);
			return getParent()->notify(pEvent);
		}
	}

	return iRet;
}

int CFrame::setFocus(bool bHasFocus)
{
	if (this->isFocusable())
	{

		if (bHasFocus == this->hasFocus())
		{
			return ERR_NO_CHANGE;
		}

		m_bHasFocus = bHasFocus;

		CFrame *pCurFrame = this;
		do
		{
			CPanel * pPanelParent = dynamic_cast<CPanel *>(pCurFrame);
			if (NULL != pPanelParent)
			{
				if (m_bHasFocus)
				{
					CFrame *pOldFocusObject =
							((CPanel *) (pPanelParent))->getFocusObject();
					if (NULL != pOldFocusObject)
					{
						pOldFocusObject->setFocus(false);
					}
					((CPanel *) (pPanelParent))->setFocusObject(this);
					this->onSetFocus();
				}
				else
				{
					((CPanel *) (pPanelParent))->setFocusObject(NULL);
					this->onLostFocus();
				}
				break;
			}
			else
			{
				pCurFrame = pCurFrame->getParent();
			}
		}while(NULL != pCurFrame);

		return ERR_SUCCESS;


//		CPanel *pActivePanel = AfwGetContext()->getActivePanel();
//		if (NULL == pActivePanel)
//		{
//			return ERR_NO_ACTIVE_PANEL;
//		}
//
//		if (bHasFocus == this->hasFocus())
//		{
//			return ERR_NO_CHANGE;
//		}
//
//		if (bHasFocus)
//		{
//			CFrame *pOldFocusObject = pActivePanel->getFocusObject();
//			if (NULL != pOldFocusObject)
//			{
//				pOldFocusObject->setFocus(false);
//			}
//			pActivePanel->setFocusObject(this);
//		}
//		else
//		{
//			if (this != pActivePanel) //we can't set cur panel's parent as a focus object,so we need the judge
//			{
//				CFrame *pNewFocusObject = this->getParent();
//				pActivePanel->setFocusObject(pNewFocusObject);
//			}
//
//
//		}

//		m_bHasFocus = bHasFocus;
//
//		m_bHasFocus ? this->onSetFocus() : this->onLostFocus();

	//	return ERR_SUCCESS;
	}
	return ERR_UN_FOCUS_ABLE;
}

int CFrame::setRect(CRect frameRect)
{
	if (!frameRect.isValidRect())
	{
		return ERR_INVALID_RECT;
	}

	if (m_frameRect.isEqualWith(frameRect))
	{
		return ERR_NO_CHANGE;
	}

	CRect oldRect = m_frameRect;
	m_frameRect = frameRect;
	this->onSize(oldRect, m_frameRect);
	return ERR_SUCCESS;

}

void CFrame::setParent(CFrame *pParent)
{
	if (this != pParent)
	{
		m_pParent = pParent;
	}
}

void CFrame::setName(std::string strName)
{
	m_strFrameName = strName;
}

int CFrame::postEvent(int eventId, int param)
{
	CAppEvent *pAppEvent = NULL;
	OBJ_NEW(CAppEvent, pAppEvent);
	if (NULL != pAppEvent)
	{
		pAppEvent->setEventId(eventId);
		pAppEvent->setParam(param);

		return postEvent(pAppEvent);
	}
	return ERR_NO_MEMORY;
}

int CFrame::postEvent(CAppEvent *pEvent)
{
	return AfwGetAppEventQueue()->addEvent(pEvent);
}

int CFrame::invalidate()
{
	IDisplay *pDisplay = AfwGetLCDFactory()->createDisplayDevice(0);
	return this->onDraw(pDisplay);
}

int CFrame::invalidateRect(const CRect & rect)
{
	IDisplay *pDisplay = AfwGetLCDFactory()->createDisplayDevice(0);
	return ERR_SUCCESS;
}

void CFrame::preCreate()
{
}

int CFrame::onCreate()
{
	int iRet = ERR_SUCCESS;
	CKeyboardListener *pListener = new CKeyboardListener(this, true);
	if (ERR_SUCCESS != (iRet = this->addEventListener(pListener)))
	{
		pListener->destory();
		return iRet;
	}
	return ERR_SUCCESS;
}

int CFrame::onDraw(IDisplay *pDisplay)
{
	if (NULL == pDisplay)
	{
		return ERR_NULL_POINTER;
	}

	if (!this->isVisible())
	{
		return ERR_OBJECT_UN_VISIBLE;
	}

	if (this->isHightlightable())
	{
		 isHightlight() ?
				pDisplay->hightlight(m_position.getX(), m_position.getY(),
						m_frameRect.getWidth(), m_frameRect.getHight()) :
				pDisplay->unHightlight(m_position.getX(), m_position.getY(),
						m_frameRect.getWidth(), m_frameRect.getHight());
	}
	if (this->isCursorable())
	{
		if (this->hasCursor())
		{
			pDisplay->setCursor(m_position.getX(),m_position.getY());
			pDisplay->showCursor();
		}
		else
		{
			pDisplay->hideCursor();
		}
	}

	return ERR_SUCCESS;
}

void CFrame::onSetFocus()
{
}

void CFrame::onLostFocus()
{
}

void CFrame::onHightlight()
{
}

void CFrame::onUnHightlight()
{
}

int CFrame::onClose()
{
	return ERR_EVENT_UN_HANDLED;
}

int CFrame::onUpKeyPress()
{
	return ERR_EVENT_UN_HANDLED;
}

int CFrame::onDownKeyPress()
{
	return ERR_EVENT_UN_HANDLED;
}

int CFrame::onLeftKeyPress()
{
	return ERR_EVENT_UN_HANDLED;
}

int CFrame::onRightKeyPress()
{
	return ERR_EVENT_UN_HANDLED;
}

int CFrame::onEnterKeyPress()
{
	return ERR_EVENT_UN_HANDLED;
}

int CFrame::setPosition(const CPoint & pt)
{
	if (pt != this->m_position)
	{
		CPoint oldPt = m_position;
		m_position = pt;
		this->onMove(oldPt, m_position);
		return ERR_SUCCESS;
	}
	return ERR_NO_CHANGE;
}

CPoint CFrame::getPosition() const
{
	return m_position;
}

void CFrame::onSize(const CRect & oldRect, const CRect & newRect)
{
}

void CFrame::onMove(const CPoint & oldPosition, const CPoint & newPosition)
{
}

int CFrame::onEscKeyPress()
{
	return ERR_EVENT_UN_HANDLED;
}

int CFrame::show()
{
	preShow();
	return this->invalidate();
}

void CFrame::preShow()
{
}

bool CFrame::isVisible() const
{
	return this->m_bIsVisible;
}

int CFrame::setVisible(bool bVisible)
{
	if (bVisible == this->isVisible())
	{
		return ERR_NO_CHANGE;
	}
	m_bIsVisible = bVisible;
	m_bIsVisible ? this->onVisible() : this->onInvisible();
	return ERR_SUCCESS;
}

void CFrame::onVisible()
{
}

void CFrame::onInvisible()
{
}

void CFrame::destory()
{
	delete this;
}

int CFrame::setCenter()
{
	//TODO: implement later
	return ERR_SUCCESS;
}


bool CFrame::hasCursor() const
{
	return this->m_bHasCursor;
}


int CFrame::setCursor(bool bShow)
{
	if (this->isCursorable())
	{
		if (bShow == this->hasCursor())
		{
			return ERR_NO_CHANGE;
		}

		this->m_bHasCursor = bShow;

		m_bHasCursor ? this->onShowCursor() : this->onHideCursor();
		this->invalidate();
		return ERR_SUCCESS;
	}
	return ERR_UN_CURSOR_ABLE;
}



void CFrame::onShowCursor()
{
}



void CFrame::onHideCursor()
{
}

}


/* namespace NS_LCD_AFW */
